<?php
namespace library;

use exception\ValidatorException;
use Illuminate\Validation;
use Illuminate\Filesystem;
use Illuminate\Translation;
use Illuminate\Validation\DatabasePresenceVerifier;
use Zhuzhichao\BankCardInfo\BankCard;
use DB;
use Douyasi\IdentityCard\ID;
use think\log;
class Validator // extends \think\Validate
{
    static $factory = null;

    /**
     * @param $data
     * @param $rules
     * @return array
     * @throws ValidatorException
     */
    public static function make($data, $rules)
    {
        $is_default = [];
        foreach($rules as $key=>$x)
        {
            $rules[$key] = preg_replace('/\|default\:[^\|]+/', '', $x, 1, $match);
            if($match)
            {
                preg_match('/\|default:([^\|]+)/', $x, $m);
                if(isset($m[1]))
                {
                    $is_default[$key] = $m[1];
                }
                else
                {
                    $is_default[$key] = null;
                }
            }
            else
            {
                $is_default[$key] = null;
            }
        }
        if(self::$factory === null){
            $filesystem = new Filesystem\Filesystem();
            $fileLoader = new Translation\FileLoader($filesystem, THINK_PATH.'/../application/config');
            $translator = new Translation\Translator($fileLoader, 'extra');
            $factory = new Validation\Factory($translator);

            $database = [
                'driver'    => 'mysql',
                'host'      => env('DB_HOST', '127.0.0.1'),
                'database'  => env('DB_NAME', 'h'),
                'username'  => env('DB_USER', 'root'),
                'password'  => env('DB_PASS', 'root'),
                'port'      => env('DB_PORT', '65501'),
                'charset'   => 'utf8',
                'collation' => 'utf8_unicode_ci',
                'prefix'    => '',
            ];
            $connection = new DB();
            $connection->addConnection($database);
            $connection->bootEloquent();
            $connection->setAsGlobal();
            $factory->setPresenceVerifier(new DatabasePresenceVerifier($connection->getDatabaseManager()));

            $factory->extend('list', function ($attribute, $value, $parameters, $validator) {
                if(!is_array($value)) $value = explode(',', $value);
                foreach($value as $item){
                    if($parameters[0] == 'integer' && !is_numeric($item))
                        throw new ValidatorException($attribute . ' 的每项必须为'.$parameters[0].'的类型', ValidatorException::BAD_VALIDATOR_PARAMS);
                }
                return true;
            });

            $factory->extend('csrf', function ($attribute, $value, $parameters, $validator) {
                return $value == md5('SECRET.XXX'.\think\Request::instance()->ip());
            });

            $factory->extend('cellphone', function ($attribute, $value, $parameters, $validator) {
                return preg_match('/^1(2|3|4|5|7|6|8|9)\d{9}$/', $value);

            });
            $factory->extend('idcard', function ($attribute, $value, $parameters, $validator) {
                $ID = new ID();
                return $ID->validateIDCard($value);
            });

            $factory->extend('length', function ($attribute, $value, $parameters, $validator) {
                return strlen($value) == ($parameters[0]??0);
            });

            $factory->extend('length_between', function ($attribute, $value, $parameters, $validator) {
                return (strlen($value) > $parameters[0]??0 )&&(strlen($value) < $parameters[1] ?? 0);
            });

            $factory->extend('bankcard', function ($attribute, $value, $parameters, $validator) {
                try{
                    $card = \Bank::card($value);
		}catch(\Exception $e){
	#		echo 'error_1';exit();
                    throw new ValidatorException('获取银行卡信息失败，请检查并重试', ValidatorException::BAD_VALIDATOR_PARAMS);
                }

		if(!isset($card['validated']))
	#		echo 'error_2';exit();
                    throw new ValidatorException('获取银行卡信息失败，请检查并重试', ValidatorException::BAD_VALIDATOR_PARAMS);
		/*
                if(!$card['validated'])
                    throw new ValidatorException('银行卡无效', ValidatorException::BAD_VALIDATOR_PARAMS);
		*/
                if($card['cardType'] == 'CC')
                    throw new ValidatorException('不支持信用卡', ValidatorException::BAD_VALIDATOR_PARAMS);

                if(!isset(config('bank')[$card['bank']]))
                    throw new ValidatorException('不支持'.($card['bankName'] ?? $card['bank'] ?? '这张').'银行卡', ValidatorException::BAD_VALIDATOR_PARAMS);

                return true;
            });

            $factory->extend('float_digits', function ($attribute, $value, $parameters, $validator) {
                $value = (float) $value;
                $string = (string) $value;
                $divided = explode('.', $string);
                if(!count($parameters) == 2)
                    throw new ValidatorException(null, ValidatorException::BAD_VALIDATOR_PARAMS);

                if(!isset($divided[1]) && $parameters[0] == 0)
                    return true;

                if(isset($divided[1]) && strlen($divided[1]) <= $parameters[1] && strlen($divided[1]) >= $parameters[0])
                    return true;

                return false;
            });

            $factory->extend('exists_in', function ($attribute, $value, $parameters, $validator) {
                if(($parameters[0] == true && trim($value)) || ($parameters[0] == false) ){
                    if(count($parameters) < 2) $parameters[1] = 'id';

                    $column = $parameters[1];
                    $exists = \think\Db::table($parameters[0])->where([$column => $value]);
                    if(isset($parameters[2]))
                    {
                        parse_str($parameters[2], $xx);
                        if($xx)
                        {
                            $exists = $exists->where($xx);
                        }
                    }
                    $attribute_name = config('validation.attributes')[$attribute] ?? $attribute;

                    $exists = $exists->find();
                    if(!$exists)
                        throw new ValidatorException($attribute_name.' 不存在', ValidatorException::BAD_VALIDATOR_PARAMS);
                }
                return true;
            });

            $factory->extend('unique_in', function ($attribute, $value, $parameters, $validator) {
                Log::info('属性'.json_encode($attribute));
                if(($parameters[0] == true && trim($value)) || ($parameters[0] == false) ){
                    if(count($parameters) < 2) $parameters[1] = 'id';

                    $column = $parameters[1];
                    $exists = \think\Db::table($parameters[0])->where([$column => $value]);
                    if(isset($parameters[2]))
                    {
                        parse_str($parameters[2], $xx);
                        if($xx)
                        {
                            $exists = $exists->where($xx);
                        }
                    }
                    $attribute_name = config('validation.attributes')[$attribute] ?? $attribute;

                    $exists = $exists->find();
                    if($exists)
                        throw new ValidatorException($attribute_name.' 已存在', ValidatorException::BAD_VALIDATOR_PARAMS);
                }
                return true;
            });

            $factory->extend('exists_if', function ($attribute, $value, $parameters, $validator) {
                if(($parameters[0] == true && trim($value)) || ($parameters[0] == false && !trim($value)) ){
                    if(count($parameters) < 3) $parameters[2] = 'id';

                    $column = $parameters[2];
                    $attribute_name = config('validation.attributes')[$attribute] ?? $attribute;

                    $exists = \think\Db::table($parameters[1])->where([$column => $value])->find();
                    if(!$exists)
                        throw new ValidatorException($attribute_name.' 不存在', ValidatorException::BAD_VALIDATOR_PARAMS);
                }
                return true;
            });

            $factory->extend('default', function ($attribute, $value, $parameters, $validator) {
                return true;
            });

            $factory->extend('unique_if', function ($attribute, $value, $parameters, $validator) {
                if(($parameters[0] == true && trim($value)) || ($parameters[0] == false && !trim($value)) ){
                    if(count($parameters) < 3) $parameters[2] = 'id';

                    $column = $parameters[2];
                    $attribute_name = config('validation.attributes')[$attribute] ?? $attribute;

                    $exists = \think\Db::table($parameters[1])->where([$column => $value])->find();
                    if($exists)
                        throw new ValidatorException($attribute_name.' 00000已存在', ValidatorException::BAD_VALIDATOR_PARAMS);
                }
                return true;
            });

            $factory->extend('null_if', function ($attribute, $value, $parameters, \Illuminate\Validation\Validator $validator) {
                $cond = $validator->getData()[$parameters[0]];
                $match = false;
                for($i = 1; $i < count($parameters); $i++)
                {
                    if($cond == $parameters[$i]){
                        $match = true;
                        break;
                    }
                }
                if($match)
                {
                    if(!empty($value) && $value !== 0 && $value !== '0') return false;
                }
                return true;
            });

            self::$factory = $factory;
        }else{
            $factory = self::$factory;
        }

        $messages = config('validation')['custom'];
        $validator = $factory->make($data, $rules, $messages);
        if($validator->fails()){
            throw new ValidatorException(implode('，', $validator->errors()->all()), ValidatorException::BAD_PARAMS);
        }

        $return = [];
        foreach($rules as $key=>$x)
        {
            $value = $data[$key] ?? $is_default[$key] ?? '';
            if(($value === NULL || $value === "") && $is_default[$key] !== NULL)
            {
                $value = $is_default[$key];
            }
            if(null === $value || '' === $value)
            {
            }
            if(preg_match('/list\:/', $rules[$key]))
            {
                if(is_null($value)) $value = '';
                $value = explode(',', $value); 
            }
            $return[] = $value;
        }

        return $return;
    }
}
